#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "mem_pool.h"



void* mp_alloc(int size)
{
	return malloc(size);
}

void mp_free(void* p)
{
	free(p);
}





/*
#define FREE 0
#define FULL 1
#define USABLE 2

typedef struct 
{
    uint next_offset;
    uint max_offset;
   
    block *pool_address;
    block *free_blocks;
    block *base_address;

    int ref;
    int state;
    int next_pool;                   //next usable pool
    int prev_pool;                   //previous usable pool
}POOL_HEADER;

static POOL_HEADER mpools[ NPOOLS ];

static int usable_head;             //index to the usable pool list header
static int free_head;               //index to the free pool list header

static void pool_create();
static block *page_alloc();
static int in_mpool(block *address, int *index);
static void pool_remove(int index);
static void page_free(block *address, int index);



void mp_init();
block *mp_alloc(uint size, int opinion);
block *mp_realloc(block *address, uint size);
void mp_free(block *address);


void mp_init()
{

    int i;
    for (i = 0; i < NPOOLS; i++)
    {
        mpools[i].ref = 0;
        mpools[i].next_offset = 0; 
        mpools[i].max_offset = POOL_SIZE - BLOCK_SIZE;
        mpools[i].pool_address = NULL;
        mpools[i].base_address = NULL;
        mpools[i].free_blocks = NULL;
        mpools[i].next_pool = ((i == NPOOLS - 1) ? -1 : (i + 1));
        mpools[i].prev_pool = i - 1;
        mpools[i].state = FREE;  
    }

    usable_head = -1;
    free_head = 0;

}

block *mp_alloc(uint size, int opinion)
{
    block *address;

    if (BIGMEM == opinion)
        address = (block *)malloc(size);

    else if (CHANGABLE == opinion)
        address = (block *)malloc(2 * size);
    
    else if (PAGE == opinion)
        address = (block *)page_alloc();

    if (NULL == address)
    {
        //write err massage to log
        exit(-1);
    }

    return address;
}

block *mp_realloc(block *address, uint size)
{
    return realloc((void *)address, (size_t)size);
}

void mp_free(block *address)
{
    int index;
    if (in_mpool(address, &index))
        page_free(address, index);
    else 
        free((void *)address);
}


static void pool_create()
{
    int temp;

    if (-1 == free_head)
    {
        //write to log
        //all pools are full
        exit(-1);
    }
    
    block *address; 

    address = (block *)malloc(POOL_SIZE + ALIGNMASK);
    mpools[free_head].base_address = address;
    mpools[free_head].pool_address = (block *)(((uint)address + ALIGNMASK) & ~ALIGNMASK);

    if (mpools[free_head].pool_address == NULL)
    {
        //write to log
        exit(-1);
    }
    
    mpools[free_head].free_blocks = mpools[free_head].pool_address;
    *(block **)mpools[free_head].free_blocks = NULL;
    mpools[free_head].state = USABLE;
   
    temp = free_head;
    free_head = mpools[free_head].next_pool;
    if (free_head != -1)
        mpools[free_head].prev_pool = -1;
  
    mpools[temp].prev_pool = -1;
    mpools[temp].next_pool = usable_head;
    usable_head = temp;

}

static block *page_alloc()
{
    block *address = NULL;
    int index;

    if (-1 == usable_head)
    {
        pool_create();
    }
    
    index = usable_head;
    mpools[index].ref++;
    
    if (*(block **)mpools[index].free_blocks != NULL)
    {
        address = mpools[index].free_blocks;
        mpools[index].free_blocks = *(block **)mpools[index].free_blocks;
    }

    else   
    {
        address = mpools[index].free_blocks; 
        mpools[index].next_offset += BLOCK_SIZE;
        mpools[index].free_blocks= (block *)((uint)mpools[index].pool_address + mpools[index].next_offset); 
        *(block **)mpools[index].free_blocks= NULL;
    }

    if (POOL_SIZE/BLOCK_SIZE == mpools[index].ref)
    {
        mpools[index].state = FULL;
        pool_remove(index);
    }
    return address;
}

static void pool_remove(int index)
{
    usable_head = mpools[index].next_pool;
    mpools[index].next_pool = -1;

    if (usable_head != -1) 
        mpools[usable_head].prev_pool = -1; 
}

static void page_free(block *address, int index)
{
    if (((uint)address & ALIGNMASK) != 0) 
    {
        //write to log
        exit(-1);
    }

    if (FULL == mpools[index].state)
    {
        mpools[index].state = USABLE;
        mpools[index].next_pool = usable_head;
        if (usable_head != -1) 
            mpools[usable_head].prev_pool = index;
        usable_head = index;
    }
    
    *(block **)address = mpools[index].free_blocks;
    mpools[index].free_blocks= address;
    mpools[index].ref--;

    if (mpools[index].ref == 0)
    {
        free((void *)mpools[index].base_address);
     
        pool_remove(index);
        mpools[index].next_offset = 0;
        mpools[index].pool_address = NULL;
        mpools[index].base_address = NULL;
        mpools[index].free_blocks = NULL;
        mpools[index].state = FREE;
        mpools[index].next_pool = free_head;
        mpools[index].prev_pool = -1;
        free_head = index;
    }
}

static int in_mpool(block *address, int *index)
{
    int i;
    block *pool_address;
    for (i = 0; i < NPOOLS; i++)
    {
        pool_address = mpools[i].pool_address;

        if (pool_address != NULL)
        {
            if ((uint)address >= (uint)pool_address && (uint)address < (uint)pool_address + POOL_SIZE)
            {    
                *index = i;
                return 1;
            } 
        }
    }
    return 0;
}
*/
